package com.invengo.base.http;

import android.content.Context;
import android.text.TextUtils;


import androidx.annotation.NonNull;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.invengo.base.BuildConfig;

import me.goldze.mvvmhabit.utils.constant.Constants;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import me.goldze.mvvmhabit.http.cookie.CookieJarImpl;
import me.goldze.mvvmhabit.http.cookie.store.PersistentCookieStore;
import me.goldze.mvvmhabit.http.interceptor.BaseInterceptor;
import me.goldze.mvvmhabit.http.interceptor.CacheInterceptor;
import me.goldze.mvvmhabit.http.interceptor.logging.Level;
import me.goldze.mvvmhabit.http.interceptor.logging.LoggingInterceptor;
import me.goldze.mvvmhabit.utils.KLog;
import me.goldze.mvvmhabit.utils.Utils;
import me.goldze.mvvmhabit.utils.cache.ACache;
import me.goldze.mvvmhabit.utils.cache.AKey;
import me.jessyan.retrofiturlmanager.RetrofitUrlManager;
import okhttp3.Cache;
import okhttp3.ConnectionPool;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.internal.platform.Platform;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.Headers;

/**
 * Created by goldze on 2017/5/10.
 * RetrofitClient封装单例类, 实现网络请求
 */
public class RetrofitClient {
    //超时时间
    private static final int DEFAULT_TIMEOUT = 25;
    //缓存时间
    private static final int CACHE_TIMEOUT = 10 * 1024 * 1024;
    //服务端根路径

    private static Context mContext = Utils.getContext();

    private static OkHttpClient okHttpClient;
    private static Retrofit retrofit;

    private Cache cache = null;
    private File httpCacheDirectory;

    private static class SingletonHolder {
        private static RetrofitClient INSTANCE = new RetrofitClient();
    }

    public static RetrofitClient getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private RetrofitClient() {

        this(Constants.DEFAULT_BASE_URL, null);
    }

    private RetrofitClient(String url, Map<String, String> headers) {
        String baseUrl = ACache.getInstance().getAsString(AKey.CACHE_HOST);
        if (TextUtils.isEmpty(baseUrl)) {
            baseUrl = url;
        }
        if (httpCacheDirectory == null) {
            httpCacheDirectory = new File(mContext.getCacheDir(), "goldze_cache");
        }

        try {
            if (cache == null) {
                cache = new Cache(httpCacheDirectory, CACHE_TIMEOUT);
            }
        } catch (Exception e) {
            KLog.e("Could not create http cache", e);
        }
        HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory();
        okHttpClient = RetrofitUrlManager.getInstance().with(
                new OkHttpClient.Builder()
                        .cookieJar(new CookieJarImpl(new PersistentCookieStore(mContext)))
                        .cache(cache)
                        .addInterceptor(new BaseInterceptor(headers))
                        .addInterceptor(chain -> {
                            Request original = chain.request();
                            if (BuildConfig.DEVICE_MODULE == "Robot_Orionstar") {
                                Request request = original.newBuilder()
                                        .header("Content-Type", "application/json; charset=utf-8")
                                        .header("Authorization", "Bearer " + ACache.getInstance().getAsString(AKey.ROBOT_TOKEN))
//                                        .header("Abp.TenantId",  ACache.getInstance().getAsString(AKey.ROBOT_TENANT_ID))
                                        .build();
                                return chain.proceed(request);
                            }
                            switch (com.invengo.library_db.BuildConfig.CUSTOM_MADE) {
                                case "YunNan_KunMing_Art":
                                    Request request = original.newBuilder()
                                            .header("loginid", ACache.getInstance().getAsString(AKey.CACHE_USER_STAFF_ID))
                                            .build();
                                    return chain.proceed(request);
                                default:
                                    return chain.proceed(original);
                            }
                        })
//                                .addInterceptor(new CacheInterceptor(mContext))
                        .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                        .addInterceptor(new LoggingInterceptor
                                        .Builder()//构建者模式
                                        .loggable(BuildConfig.DEBUG) //是否开启日志打印
                                        .setLevel(Level.BASIC) //打印的等级
                                        .log(Platform.INFO) // 打印类型
                                        .request("Request") // request的Tag
                                        .response("Response")// Response的Tag
//                                .addHeader("log-header", "I am the log request header.") // 添加打印头, 注意 key 和 value 都不能是中文
                                        .build()
                        )
                        .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                        .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                        .pingInterval(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                        .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                        .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)

                        .connectionPool(new ConnectionPool(8, 15, TimeUnit.SECONDS))
        ).build(); // 这里你可以根据自己的机型设置同时连接的个数和时间，我这里8个，和每个保持时间为10s)

        Gson gson = new GsonBuilder().registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory()).create();

        if (BuildConfig.DEVICE_MODULE == "Robot_Orionstar") {
            retrofit = new Retrofit.Builder()
                    .client(okHttpClient)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .baseUrl(baseUrl)
                    .build();
        } else {
            retrofit = new Retrofit.Builder()
                    .client(okHttpClient)
//                    .addConverterFactory(GsonConverterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .baseUrl(baseUrl)
                    .build();
        }

    }

    /**
     * create you ApiService
     * Create an implementation of the API endpoints defined by the {@code service} interface.
     */
    public <T> T create(final Class<T> service) {
        if (service == null) {
            throw new RuntimeException("Api service is null!");
        }
        return retrofit.create(service);
    }

    /**
     * /**
     * execute your customer API
     * For example:
     * MyApiService service =
     * RetrofitClient.getInstance(MainActivity.this).create(MyApiService.class);
     * <p>
     * RetrofitClient.getInstance(MainActivity.this)
     * .execute(service.lgon("name", "password"), subscriber)
     * * @param subscriber
     */

    public static <T> T execute(Observable<T> observable, Observer<T> subscriber) {
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);

        return null;
    }
}
